import math

class PenmanMonteith:
	"""
	蒸散量模型计算
	"""
	
	def __init__(self):
		
		self.setDate()
		
		# 气象数据
		self.getWeather() 
		
		# 温度数据
		self.getTemperature() 
		
		# 湿度数据
		self.getHumidity()
		
		# 地理位置
		self.getGeography()
		
		# 田块信息
		self.getCropland()
		
	def setDate(self):
		"""
		需计算日期
		"""
		self.date = system.date.now()
		
		
	def getCropland(self):
		"""
		田块信息
		"""
		# 作物生张阶段Kc
		kc = system.tag.read("[default]Cropland 1/Kc").value
		self.kc = kc
		
		# 作物参数信息
		row = system.db.runNamedQuery("cropland/select_details", {"id": 4})[0]
		
		self.FieldCapacity = row["water_Holding_capacity"] # 田间持水量
		self.BulkDensity = row["bulk_density"] # 土壤容重
		self.SoilMoistureContent = row["water_content"] # 土壤含水量
		self.LandArea = row["soil_area"] # 土地面积  亩
		self.IrrigationDepth = row["irrigation_depth"] # 浇灌深度
		self.SprinklerIrrigation = row["irrigation_available"] # 灌溉方式 利用率 喷灌
		self.Elevation = row["altitude"] # 海拔(z)
		
	def getWeather(self):
		"""
		气象站数据
		"""
		
		sql = "SELECT TOP 1 * FROM [dbo].[Weather] WHERE fxDate = '{}'".format(system.date.format(self.date, "yyyy-MM-dd"))
		ds = system.db.runQuery(sql, Env.databases["connection"])
		
		if not ds.getRowCount():
			raise Exception('weather is null')
		
		row = ds[0]
		
		self.pe = 0 # row["precip"] # 大棚降水量 
		self.WindSpeed = 2.5 # row["windSpeedDay"] # 风速 m/s
		
		sunrise = system.date.parse(row["sunrise"], "HH:mm") # 日出
		sunset = system.date.parse(row["sunset"], "HH:mm") # 日落
		self.SunshineDuration = system.date.minutesBetween(sunrise, sunset) / 60.0 # 日照时数(n)
	
	def getTemperature(self):
		"""
		获取温度数据
		"""
		
		paths = [
			"[default]Air 1/Temperature",
			"[default]Air 2/Temperature",
			"[default]Air 3/Temperature",
		]
		
		end = system.date.now()
		start = system.date.addMinutes(end, -20)
		
		calc = ["Minimum", "Maximum"]
		
		data = system.tag.queryTagCalculations(paths, calc, start, end)
		
		minTemp = system.math.min([data.getValueAt(index, "Minimum") for index in range(data.getRowCount())])
		maxTemp = system.math.max([data.getValueAt(index, "Maximum") for index in range(data.getRowCount())])
		
		self.Tmax = maxTemp # 最高气温
		self.Tmin = minTemp # 最低气温
	
	def getHumidity(self):
		"""
		获取湿度数据
		"""
		
		paths = [
			"[default]Air 1/Humidity",
			"[default]Air 2/Humidity",
			"[default]Air 3/Humidity",
		]
		end = system.date.now()
		start = system.date.addMinutes(end, -20)
		
		calc = ["SimpleAverage"]
		data = system.tag.queryTagCalculations(paths, calc, start, end)
		
		avg = data.getValueAt(0, "SimpleAverage")
		
		self.RHmean = avg # 相对湿度
		
	def getGeography(self):
		"""
		地理位置
		"""
		self.Latitude = "40°30′N" # 纬度(φ)
		
		
	def calculate(self):
		"""
		数据计算
		"""
	
		# 平均气温T
		T = (self.Tmax + self.Tmin) / 2
		print u"平均气温T:", T
		
		# 饱和水汽压es
		es = (0.6108*math.exp(17.27* self.Tmax /(self.Tmax +237.3)) + 0.6108 * math.exp(17.27* self.Tmin /(self.Tmin + 237.3))) / 2
		print u"饱和水汽压es:", es
		
		# 实际水汽压ea
		ea = es * self.RHmean / 100
		print u"实际水汽压ea:", ea
		
		# 饱和水汽压曲线斜率Δ
		Delta = 4098 * es / ((T+237.3)*(T+237.3))
		print u"饱和水汽压曲线斜率Δ:", Delta
		
		# 净辐射Rn
		Rn = 26.34
		
		# 土壤热通量G
		G = 0.1 * Rn
		
		# 海拔修正P
		P = 101.3 * pow((293-0.0065 * self.Elevation) / 293, 5.26)
		print u"海拔修正P:", P
		
		# 湿度计常数γ
		PsychrometricConstant = (1.013 * 0.001 * P)/(2.45 * 0.622)
		print u"湿度计常数γ:", PsychrometricConstant
		
		# 参考作物蒸散量ETo
		eto = (0.408*Delta*(Rn-G)+PsychrometricConstant*900/(T+273)*self.WindSpeed*(es-ea))/(Delta+PsychrometricConstant*(1+0.34*self.WindSpeed))
		print u"参考作物蒸散量ETo:", eto
		
		IrrigationVolume = (eto * self.kc - self.pe + (self.IrrigationDepth * (self.FieldCapacity - self.SoilMoistureContent) * self.BulkDensity)) / self.SprinklerIrrigation
		print u"单位面积灌水量:", IrrigationVolume
		
		DayIrrigationVolume = IrrigationVolume * self.LandArea * 666.67 / 1000
		print u"日需灌溉量:", DayIrrigationVolume
		
		return DayIrrigationVolume
		
class Fertilization:
	"""
	追肥量模型计算
	"""
	
	NDVI = 0.4
	
	Stages = [u"盛蕾期", u"花期", u"盛玲期", u"初絮期"]
	NDVIS = [0.695, 0.833, 0.881, 0.809]
	NitrogenFertilizer = [0.016, 0.061, 0.074, 0.011]
	
	def __init__(self):
		
		index = min(range(len(self.NDVIS)), key=lambda i: abs(self.NDVIS[i] - self.NDVI))
		
		NDVIValue = self.NDVIS[index]
		for index, value in enumerate(self.Stages):
			print (NDVIValue - self.NDVI) * self.NitrogenFertilizer[index]
	
	
	
	
	
	
	